﻿/**************************************************************
 *
 * 唯一标识：964c620c-6b8f-4b3d-bce4-25d9047cd7cc
 * 命名空间：Microsoft.Extensions.Hosting
 * 创建时间：2023/8/1 8:37:38
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：NLog配置扩展类
 *
 **************************************************************/

using NLog;
using NLog.Config;
using NLog.Layouts;
using NLog.Targets;
using NLog.Web;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Microsoft.Extensions.Hosting
{
    /// <summary>
    /// NLog配置扩展类
    /// </summary>
    public static class ConfigureExtensions
    {
        private const string FALLBACK_LAYOUT = "${longdate}|${level:uppercase=true}|${logger}|${message}${onexception:${newline}${exception:format=tostring}}";

        /// <summary>
        /// 使用NLog配置Web应用
        /// </summary>
        /// <param name="builder">主机构建器</param>
        /// <param name="configureOptions">配置选项回调</param>
        /// <returns>配置后的主机构建器</returns>
        public static IHostBuilder UseNLogWeb(this IHostBuilder builder,
            Action<LoggingConfiguration>? configureOptions = null)
        {
            try
            {
                // 加载配置
                var config = LoadNLogConfiguration();

                // 应用自定义配置
                configureOptions?.Invoke(config);

                // 应用配置
                LogManager.Configuration = config;

                // 记录配置完成
                var logger = LogManager.GetCurrentClassLogger();
                logger.Info("NLog configuration initialized successfully.");

                return builder.UseNLog();
            }
            catch (Exception ex)
            {
                // 如果配置失败，使用基本配置
                ConfigureFallbackLogging(ex);
                return builder.UseNLog();
            }
        }

        /// <summary>
        /// 加载NLog配置
        /// </summary>
        private static LoggingConfiguration LoadNLogConfiguration()
        {
            // 检查现有配置
            if (LogManager.Configuration != null && LogManager.Configuration.LoggingRules.Count > 0)
            {
                return LogManager.Configuration;
            }

            // 尝试加载环境特定的配置文件
            var environment = (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "development").ToLower();
            var configPaths = new[]
            {
                $"nlog.{environment}.config"
            };

            foreach (var configPath in configPaths)
            {
                if (File.Exists(configPath))
                {
                    return new XmlLoggingConfiguration(configPath);
                }
            }

            // 如果没有找到配置文件，创建默认配置
            return CreateDefaultConfiguration();
        }

        /// <summary>
        /// 创建默认配置
        /// </summary>
        private static LoggingConfiguration CreateDefaultConfiguration()
        {
            var config = new LoggingConfiguration();

            // 创建默认目标
            var fileTarget = new FileTarget("defaultFile")
            {
                FileName = "${basedir}/logs/log-${shortdate}.log",
                Layout = Layout.FromString(FALLBACK_LAYOUT)
            };

            var consoleTarget = new ConsoleTarget("defaultConsole")
            {
                Layout = Layout.FromString(FALLBACK_LAYOUT)
            };

            config.AddTarget(fileTarget);
            config.AddTarget(consoleTarget);

            // 添加默认规则
            var minLevel = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"
                ? LogLevel.Info
                : LogLevel.Warn;

            config.AddRule(minLevel, LogLevel.Fatal, fileTarget);
            config.AddRule(minLevel, LogLevel.Fatal, consoleTarget);

            return config;
        }

        /// <summary>
        /// 配置回退日志记录
        /// </summary>
        private static void ConfigureFallbackLogging(Exception originalException)
        {
            try
            {
                var config = new LoggingConfiguration();
                var consoleTarget = new ConsoleTarget("fallback")
                {
                    Layout = Layout.FromString(FALLBACK_LAYOUT)
                };

                config.AddTarget(consoleTarget);
                config.AddRule(LogLevel.Warn, LogLevel.Fatal, consoleTarget);

                LogManager.Configuration = config;

                var logger = LogManager.GetCurrentClassLogger();
                logger.Error(originalException, "Failed to load NLog configuration. Using fallback configuration.");
            }
            catch (Exception fallbackEx)
            {
                // 如果连回退配置都失败了，至少在控制台输出错误
                Console.Error.WriteLine($"Critical error in logging configuration: {fallbackEx.Message}");
                Console.Error.WriteLine($"Original error: {originalException.Message}");
            }
        }
    }
}